package craky.keeper.pane;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.border.EmptyBorder;

import sun.swing.SwingUtilities2;
import craky.componentc.JCLabel;
import craky.keeper.util.KeeperUtil;
import craky.util.UIUtil;

public class KeeperGlassPane extends JComponent
{
    private static final long serialVersionUID = -6019223838096521332L;

    private static final Color BACKGROUND = new Color(0, 0, 0, 200);

    private int arc;

    private Window window;

    private boolean windowMoveable;

    private JCLabel lbInfo;

    private boolean visible;

    public KeeperGlassPane(Window window)
    {
        this.window = window;
        this.windowMoveable = true;
        this.arc = 3;
        this.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, UIUtil.COMMON_AATEXT_INFO);
        this.setBorder(new EmptyBorder(1, 1, 1, 1));
        this.setLayout(new BorderLayout());
        this.createInfoLabel();
        this.setFocusTraversalKeysEnabled(false);
        MouseHandler mouseHandler = new MouseHandler();
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
        this.addKeyListener(new KeyAdapter(){});
        this.addComponentListener(new ComponentAdapter()
        {
            public void componentShown(ComponentEvent evt)
            {
                requestFocusInWindow();
            }
        });
    }

    private void createInfoLabel()
    {
        lbInfo = new JCLabel();
        lbInfo.setVerticalAlignment(JCLabel.CENTER);
        lbInfo.setHorizontalAlignment(JCLabel.CENTER);
        lbInfo.setVerticalTextPosition(JLabel.CENTER);
        lbInfo.setHorizontalTextPosition(JLabel.RIGHT);
        lbInfo.setIconTextGap(10);
        lbInfo.setIcon(KeeperUtil.getIcon("loading.gif"));
        Font font = lbInfo.getFont();
        font = font.deriveFont(16f);
        lbInfo.setFont(font);
        lbInfo.setForeground(Color.YELLOW);
        this.add(lbInfo, BorderLayout.CENTER);
    }

    public void doTask(String info, final Runnable run, final JComponent actionComponent)
    {
        if(actionComponent != null)
        {
            actionComponent.setEnabled(false);
        }

        lbInfo.setText(info);
        this.visible = true;
        new Thread()
        {
            public void run()
            {
                run.run();
                setVisible(false);

                if(actionComponent != null)
                {
                    actionComponent.setEnabled(true);
                }
            }
        }.start();
        new Thread()
        {
            public void run()
            {
                try
                {
                    sleep(100);

                    if(visible)
                    {
                        setVisible(true);
                    }
                }
                catch(Exception e)
                {}
            }
        }.start();
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(BACKGROUND);
        Insets insets = this.getInsets();
        int width = this.getWidth() - insets.left - insets.right;
        int height = this.getHeight() - insets.top - insets.bottom;
        g2d.fillRoundRect(insets.left, insets.top, width, height, arc, arc);
    }

    @Override
    public void setVisible(boolean visible)
    {
        this.visible = visible;
        super.setVisible(visible);
    }

    public boolean isWindowMoveable()
    {
        return this.windowMoveable;
    }

    public void setWindowMoveable(boolean windowMoveable)
    {
        this.windowMoveable = windowMoveable;
    }

    public int getArc()
    {
        return this.arc;
    }

    public void setArc(int arc)
    {
        this.arc = arc;
    }

    private class MouseHandler extends MouseAdapter
    {
        private Point point = new Point(-1, -1);

        public void mouseDragged(MouseEvent e)
        {
            boolean move = windowMoveable;

            if(move && window instanceof Frame)
            {
                move = (((Frame)window).getExtendedState() & Frame.MAXIMIZED_BOTH) == 0;
            }

            if(move && point.x >= 0 && point.y >= 0)
            {
                Point locationOnScreen = e.getLocationOnScreen();
                int x = locationOnScreen.x - point.x;
                int y = locationOnScreen.y - point.y;
                window.setLocation(x, y);
            }
        }

        public void mousePressed(MouseEvent e)
        {
            if(windowMoveable)
            {
                if(e.getButton() == MouseEvent.BUTTON1)
                {
                    point.move(e.getXOnScreen() - window.getX(), e.getYOnScreen() - window.getY());
                }
                else
                {
                    point.move(-1, -1);
                }
            }
        }

        public void mouseReleased(MouseEvent e)
        {
            if(windowMoveable && e.getButton() == MouseEvent.BUTTON1)
            {
                point.move(-1, -1);
            }
        }
    }
}
